﻿//Copyright © 2012  Daniel Lopez

//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either version 2
//of the License, or (at your option) any later version.

//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.

//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Diagnostics;
using System.Security.Cryptography;
namespace NASM_Develop_IDE
{
    public partial class CustomScriptDialog : Form
    {
        private Solution solution;
        private string output;
        public CustomScriptDialog(Solution solution)
        {
            if (solution == null) throw new ArgumentNullException("Solution must not be null!");
            InitializeComponent();
            this.solution = solution;
            TextBoxHighlighter.Highlight(binaryOutputName, "Enter Binary Output Name (Extension Is Optional)");
        }

        private void scriptType_SelectionChangeCommitted(object sender, EventArgs e)
        {
            
            int selectedIndex = scriptType.SelectedIndex;
            switch(selectedIndex)
            {
                case ScriptType.PowerShell:
                {
                    scriptEditor.Margins[0].Width = 20;
                    scriptEditor.Margins[1].Width = 32;
                    scriptEditor.Margins[1].IsMarkerMargin = true;
                    scriptEditor.Margins[1].Type = ScintillaNET.MarginType.Symbol;
                    scriptEditor.Markers[1].Symbol = ScintillaNET.MarkerSymbol.Arrows;
                    scriptEditor.Markers[1].ForeColor = Color.Red;      
                    scriptEditor.ConfigurationManager.CustomLocation = "Powershell.xml";
                    scriptEditor.ConfigurationManager.Language = "bash";
                    scriptEditor.ConfigurationManager.Configure();
                    scriptEditor.Text = "#Copyright © 2012  Daniel Lopez\r\n#This program is free software; you can redistribute it and/or\r\n#modify it under the terms of the GNU General Public License\r\n#as published by the Free Software Foundation; either version 2\r\n#of the License, or (at your option) any later version.\r\n\r\n#This program is distributed in the hope that it will be useful,\r\n#but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n#GNU General Public License for more details.\r\n\r\n#You should have received a copy of the GNU General Public License\r\n#along with this program; if not, write to the Free Software\r\n#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\r\n\r\n#Note: Script can be modified but do not modify function declaration or command line arguments.\r\n\r\n\r\nfunction Compile([string[]]$i, [string[]]$o)\r\n{\r\n    $count = $i.length\r\n    $count2 = $o.length\r\n    if ($count.Equals($count2))\r\n    {\r\n        for($index = 0; $index -lt $count; $index++)\r\n        {\r\n            nasm -fwin32 -o $o[$index] $i[$index] #Extra Arguments Here\r\n        }\r\n    }\r\n}\r\n\r\nfunction Link([string[]]$objs, [string]$o)\r\n{\r\n    $objects = \"\"\r\n    foreach($obj in $objs)\r\n    {\r\n        $objects += ($obj + \" \")\r\n    }\r\n    gcc $objects -o $o #Extra Arguments Here\r\n}\r\n\r\nif ($args.Count.Equals(3))\r\n{\r\n    if ($args[0].Count.Equals($args[1].Count))\r\n    {\r\n        \r\n        Compile $args[0] $args[1]\r\n        Link $args[1] $args[2]\r\n    }\r\n    else\r\n    {\r\n        echo \"Argument 1 and Argument 2 Must Have The Same Array Size!\"\r\n    }\r\n}\r\nelse\r\n{\r\n    echo \"Invalid amount of arguments\"\r\n}";
                    scriptEditor.Styles[2].ForeColor = Color.Green;
                    break;
                }
                case ScriptType.Batch:
                {
                    DialogResult result = MessageBox.Show("Are you sure you want the script type to be Batch?\nNote:Batch files are deprecated and Powershell provides the same functionality but more and it is recommended. Powershell is shipped with most OEM versions of Microsoft Windows. But if itsn't available in your system or it is unsupported then use Batch File Scripts.", "Are you sure?",  MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                    if (result == System.Windows.Forms.DialogResult.Yes)
                    {
                        scriptEditor.Margins[0].Width = 20;
                        scriptEditor.Margins[1].Width = 32;
                        scriptEditor.Margins[1].IsMarkerMargin = true;
                        scriptEditor.Margins[1].Type = ScintillaNET.MarginType.Symbol;
                        scriptEditor.Markers[1].Symbol = ScintillaNET.MarkerSymbol.Arrows;
                        scriptEditor.Markers[1].ForeColor = Color.Red;
                        scriptEditor.ConfigurationManager.Language = "batch";
                        scriptEditor.ConfigurationManager.Configure();
                        
                    }
                    else
                    {
                        scriptEditor.Margins[0].Width = 20;
                        scriptEditor.Margins[1].Width = 32;
                        scriptEditor.Margins[1].IsMarkerMargin = true;
                        scriptEditor.Margins[1].Type = ScintillaNET.MarginType.Symbol;
                        scriptEditor.Markers[1].Symbol = ScintillaNET.MarkerSymbol.Arrows;
                        scriptEditor.Markers[1].ForeColor = Color.Red;
                        scriptEditor.ConfigurationManager.CustomLocation = "Powershell.xml";
                        scriptEditor.ConfigurationManager.Language = "ps";
                        scriptEditor.ConfigurationManager.Configure();
                        scriptType.SelectedIndex = 1;
                        selectedIndex = 1;
                    }
                    break;
                }
            }
        }
        struct ScriptType
        {
            public const int Batch = 0;
            public const int PowerShell = 1;
        }

        private void scriptEditor_TextChanged(object sender, EventArgs e)
        {
            
        }

        private void scriptEditor_KeyUp(object sender, KeyEventArgs e)
        {

        }
        public string BuildOutput
        {
            get
            {
                return output;
            }
        }
        private void build_Click(object sender, EventArgs e)
        {
            if (scriptType.SelectedIndex == ScriptType.PowerShell)
            {
                string tempPath = Path.GetTempPath();
                string fileName = getRandomName();
                using (StreamWriter writer = new StreamWriter(tempPath + fileName))
                {
                    writer.Write(scriptEditor.Text);
                }
                if (solution.NameOfOutputBinary == "" || solution.NameOfOutputBinary == "default.exe")
                {
                    List<string> pathOfObjects = new List<string>();
                    solution.AbsolutePathOfSources.ForEach(delegate(string path)
                    {
                        pathOfObjects.Add(solution.AbsolutePathOfBinFolder + "\\" + Path.GetFileNameWithoutExtension(path) + ".obj");
                    });
                    output = NASMBuilder.BuildFromScript(tempPath + fileName, solution.AbsolutePathOfSources.ToArray(), pathOfObjects.ToArray(), solution.AbsolutePathOfBinFolder + "\\" + binaryOutputName);
                }
                else
                {
                    List<string> pathOfObjects = new List<string>();
                    solution.AbsolutePathOfSources.ForEach(delegate(string path)
                    {
                        pathOfObjects.Add(solution.AbsolutePathOfBinFolder + "\\" + Path.GetFileNameWithoutExtension(path) + ".obj");
                    });
                    output = NASMBuilder.BuildFromScript(tempPath + fileName, solution.AbsolutePathOfSources.ToArray(), pathOfObjects.ToArray(), solution.AbsolutePathOfBinFolder + "\\" + solution.NameOfOutputBinary);
                }
                try
                {
                    File.Delete(tempPath + fileName);
                }
                catch
                {
                    Console.Write("Failed To Delete Temp File!");
                }
                this.Close();

            }
            else if (scriptType.SelectedIndex == ScriptType.Batch)
            {
                MessageBox.Show("Batch Scripting Feature Unavailable! Please select a different script type.", "Feature Unavailable!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                
            }
            else
            {
                MessageBox.Show("Please select a valid script type!", "What the!", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        private string getRandomName()
        {
            RandomNumberGenerator gen = RandomNumberGenerator.Create();
            byte[] bytes = new byte[50];
            gen.GetNonZeroBytes(bytes);
            return new UnicodeEncoding().GetString(bytes) + ".ps1";
        }

        private void cancelButton_Click(object sender, EventArgs e)
        {
            this.Close();
        }
    }
}
